import hashlib
import random
import time
import uuid
from functools import wraps
from urllib.parse import urlparse

from django.contrib.auth import REDIRECT_FIELD_NAME
from django.forms import model_to_dict
from django.shortcuts import resolve_url
from django.urls import reverse, reverse_lazy
from django.core.mail import send_mail
from django.db import connection
from django.conf import settings
from django.utils import timezone

from assets.models import ProductLine, Project, Host


def cmdb_uuid() -> str:
    """
    uuid 生成
    :return:
    """
    salt_key = '1234567890abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ!@$%^&*()_'
    symbol = '!@$%^&*()_'
    salt_list = []
    for i in range(60):
        salt_list.append(random.choice(salt_key))
    for i in range(4):
        salt_list.append(random.choice(symbol))
    salt = "%s%s%s" % (''.join(salt_list), time.time(), uuid.uuid4())
    uuid_data = str(uuid.uuid3(uuid.NAMESPACE_DNS, salt))
    return uuid_data


def check_auth_func(request, data):
    """ 检查用户有权限 """

    if request.user.is_superuser:
        return True
    if request.session.get("fun_auth", False) and request.session.get("fun_auth", False).get("data", False):
        return True
    return False


def user_passes_test_ext(check_auth=check_auth_func, permission_desc=None, redirect_to=None, login_url=None,
                         redirect_field_name=REDIRECT_FIELD_NAME):
    """
    检查用户权限
    :param check_auth:
    :param permission_desc:   需要检查的权限  "add_user" , "edit_usr"
    :param redirect_to: 没有权限重定向到此url
    :param login_url:
    :param redirect_field_name:
    :return:
    """
    if redirect_to:
        login_url = reverse_lazy(redirect_to)

    def decorator(view_func):
        @wraps(view_func)
        def _wrapped_view(request, *args, **kwargs):
            if check_auth(request, permission_desc):  # 返回  True,False
                return view_func(request, *args, **kwargs)
            path = request.build_absolute_uri()
            resolved_login_url = resolve_url(login_url or settings.LOGIN_URL)
            # If the login url is the same scheme and net location then just
            # use the path as the "next" url.
            login_scheme, login_netloc = urlparse(resolved_login_url)[:2]
            current_scheme, current_netloc = urlparse(path)[:2]
            if ((not login_scheme or login_scheme == current_scheme) and
                    (not login_netloc or login_netloc == current_netloc)):
                path = request.get_full_path()
            from django.contrib.auth.views import redirect_to_login
            return redirect_to_login(
                path, resolved_login_url, redirect_field_name)

        return _wrapped_view

    return decorator


def user_register_send_email(host=None, new_user=None, ):
    """ 用户注册发送邮件 """
    if settings.EMAIL_PUSH:
        user_name = new_user.username
        pk_ = new_user.pk
        token = get_hash_token(user_name, pk_)

        init_pass_url = reverse("user_init_password")  # '/accounts/init_passsword/'

        url = 'http://%s%s?pk=%s&token=%s' % (host, init_pass_url, new_user.pk, token)
        mail_title = '运维自动化初始密码,注意密码设置需符合8位以上,字母+数字+特殊符合组合的形式'
        mail_msg = '''
        Hi,%s:
            请点击以下链接初始化运维自动化密码,此链接当天有效
            注意密码设置需符合8位以上，字母+数字+特殊符合组合的形式，否则无法登录::
                %s
            有任何问题，请随时和运维组联系。
        ''' % (new_user.username, url)

        send_mail(mail_title, mail_msg, settings.EMAIL_FROM, [new_user.email], fail_silently=False)


def user_reset_password_send_email(host=None, user_obj=None, ):
    # 用户重置密码发送邮件
    user_name = user_obj.username
    pk_ = user_obj.pk
    token = get_hash_token(user_name, pk_)

    rest_done_pass_url = reverse("user_reset_passsword_done")  # '/accounts/reset_passsword_done/'

    url = 'http://%s%s?pk=%s&token=%s' % (host, rest_done_pass_url, user_obj.pk, token)
    mail_title = '运维自动化重置密码'
    mail_msg = """
    Hi,%s:
        请点击以下链接修改密码,此链接当天有效:
            %s
        有任何问题，请随时和运维组联系。
    """ % (user_obj.username, url)

    send_mail(mail_title, mail_msg, settings.EMAIL_FROM, [user_obj.email], fail_silently=False)


def get_hash_token(username, user_pk):
    # 获取token
    str_time = time.strftime('%Y-%m-%d', time.localtime(time.time()))
    str_time = str(str_time)

    auth_key = settings.AUTH_KEY
    pk_ = str(user_pk)

    tmp_str = username + auth_key + pk_ + str_time
    encode_str = tmp_str.encode(encoding='utf-8', errors='strict')
    token = str(hashlib.sha1(encode_str).hexdigest())

    return token


def mysql_connection_raw_query_sql(sql, args=None, sql_type='SELECT'):
    """
    Mysql 连接客户端
    :param sql:
    :param args:
    :param sql_type:
    :return:
    """
    with connection.cursor() as cursor:
        cursor.execute(sql, args)
        raw_data = cursor.fetchone()
        if sql_type == 'SELECT' or sql_type == 'select':
            col_names = [desc[0] for desc in cursor.description]
            res_data = dict(zip(col_names, raw_data))

            return res_data


def ztree_tag(username, **kwargs):
    """
    """
    user_pk = kwargs.get("user_pk")

    print(user_pk,"user_pk")

    ztree_data = []
    # 产品线
    Line_RootTree_data = ProductLine.objects.all().order_by("sort")
    # 项目
    Project_RooTree_Items = Project.objects.all().order_by("sort")

    iplist = []

    # 空闲主机列表?
    idle_list = []

    # 1.产品线items
    for product_line_obj in Line_RootTree_data:
        product_line_obj_tree_pk = str(product_line_obj.pk)

        token = get_hash_token(username, product_line_obj_tree_pk)

        pt_line = "ptline_" + product_line_obj_tree_pk
        ztree_data.append({
            # 1.产品线item
            "id": pt_line,
            "pId": -99,
            "status": 1,
            "name": product_line_obj.name,
            "token": token,
            "t": product_line_obj.name,
            "uuid": pt_line,
            'dep': True,
            "open": True,
            "user": str(user_pk),
            "icon": "/static/img/zTreeStyle/img/diy/8.png",
        })

    # 2.项目items
    for project_obj in Project_RooTree_Items:
        # 获取所有项目列表
        try:

            product_line_pk = str(project_obj.line.pk)  # 产品线id
            pt_line_id = "ptline_" + product_line_pk

            token = get_hash_token(username, str(project_obj.pk))

            # 通过项目找到关联的所有主机
            host_object_list = Host.objects.filter(projects=project_obj).order_by("-env")

            pro_count = host_object_list.filter(idle=True).count()  # 使用中的主机总数
            idle_count = host_object_list.filter(idle=False).count()  # 空闲的主机总数
            if idle_count > 0:

                Pro_name = "%s  <span style='color:#1c84c6;'> (在用:%s  空闲:%s) </span>" % (
                    project_obj.project_name, pro_count, idle_count)
            else:
                Pro_name = "%s  <span style='color:#1c84c6;'> (%s) </span>" % (project_obj.project_name, pro_count)

            project_pk = f"project_{project_obj.pk}"

            # 2.项目items
            ztree_data.append(
                {
                    "id": project_pk,
                    "pId": pt_line_id,
                    "status": 2,
                    "name": Pro_name,
                    "token": token,
                    "t": project_obj.project_name,
                    "uuid": str(project_obj.pk),
                    'pos': True,
                    "open": True,
                    "user": user_pk,
                    "icon": "/static/img/zTreeStyle/img/diy/2.png",
                })

            for host_object in host_object_list:
                # 以主机ip来命名
                env_name = "%s" % host_object.eth1

                if not host_object.idle:
                    # 如果是空闲未使用
                    env_name = "<span style='color:#d9534f;'>空闲</span>_%s" % host_object.eth1
                elif host_object.env:
                    # 如果有环境配置
                    if host_object.env == "prod":
                        env_name = "<span style='color:#1c84c6;'>%s</span>_%s" % (host_object.env, host_object.eth1)
                    if host_object.env == "st":
                        env_name = "<span style='color:#ec971f;'>%s</span>_%s" % (host_object.env, host_object.eth1)
                    if host_object.env == "pub":
                        env_name = "<span style='color:#5cb85c;'>%s</span>_%s" % (host_object.env, host_object.eth1)

                # 3. 主机items
                project_pk = f"project_{project_obj.pk}"
                host_pk = f"host_{host_object.pk}"
                ztree_data.append(
                    {
                        "id": host_pk,
                        "pId": project_pk,
                        "name": env_name,
                        "status": 3,
                        "token": token,
                        "uuid": host_pk,
                        'pos': True,
                        "open": True,
                        # "icon": "/static/images/ico/linux5.png",
                        "icon": "/static/img/zTreeStyle/img/diy/linux-ico.png",
                    })
                # else:

                t_ = f"ptline_{project_obj.line_id}空闲".encode("utf8")
                idle_data = hashlib.sha1(t_).hexdigest()

                if not host_object.idle:
                    # 如果主机是未使用状态,且关联到项目 ,添加到空闲的主机列表
                    if idle_data not in idle_list:
                        idle_list.append(idle_data)
                        ztree_data.append(
                            {
                                "id": idle_data,
                                "pId": product_line_pk,
                                "status": 4,
                                "name": "<span style='color:#ed5565;'>空闲</span>",
                                "token": token,
                                "t": project_obj.project_name,
                                "uuid": str(project_obj.pk),

                            })

                    if host_object.eth1 not in iplist:
                        iplist.append(host_object.eth1)
                        ztree_data.append(
                            {
                                "id": str(host_object.pk),
                                "pId": idle_data,
                                "name": env_name,
                                "status": 3,
                                "token": token,
                                "uuid": str(host_object.pk),
                                'pos': True,
                                "open": True,
                                "icon": "/static/img/zTreeStyle/img/diy/linux-ico.png",
                            })

                        # ztree_data.append({{"pId": str(i.uuid), "name": [i[0] for i in ENVIRONMENT]}})

        except Exception as e:
            print(e)

    return ztree_data


def get_str_microsecond() -> str:
    """
    获取字符型毫秒


    :return:      '20180701191855965'
    :rtype:
    """
    now = timezone.now()
    str_time = '{:%Y%m%d%H%M%S}{:03d}'.format(now, now.microsecond // 1000)
    return str_time
